﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class PawnData : Actors
{
	[System.Serializable]
	public class PawnVisual
	{
		public PawnValue m_PawnValue;
		public Sprite m_MatchingPawnRenderer;
	}

	public class PawnMovement
	{
		public int MoveX;
		public int MoveY;

		public PawnMovement(int moveX, int moveY)
		{
			MoveX = moveX;
			MoveY = moveY;
		}
	}

	public enum PawnValue
	{
		Pawn = 0,
		Knight,
		Bishop,
		Rook,
		Queen,
		King,
		Count
	}

	public List<PawnVisual> m_PawnVisualList = new List<PawnVisual>();
	public SpriteRenderer m_SpriteRenderer;
	public SpriteRenderer m_PlayerIconRenderer;
	public Animator m_Animator;
	public GameObject m_IconVisual;
	public float m_PlayerIconFlickerTime = 0.25f;
	public float m_PlayerScaleSpeed = 0.5f;
	public float m_DeadPosSpeed = 5f;
	public Vector3 m_NewPlayerScale;

	private PawnValue m_PawnValue;
	public PawnValue Value
	{
		get { return m_PawnValue; }
	}

	private bool m_IsDead;
	public bool IsDead
	{
		set { m_IsDead = value; }
	}
	
	private bool m_ReachedDeadPos;
	public bool ReachedDeadPos
	{
		get { return m_ReachedDeadPos; }
	}

	private List<PawnMovement> m_PawnMovement = new List<PawnMovement>();
	private SpriteRenderer m_PawnVisual;
	private int m_LargestMoveCheck;

	private Color m_PlayerIconNewAlpha;
	private bool m_PlayerIconNewAlphaReached;
	private float m_PlayerIconFlickerTimer;
	public float PlayerIconFlickerTimer
	{
		set { m_PlayerIconFlickerTimer = value; }
	}

	private Vector3 m_InitialScale;
	private bool m_PlayerScaleReached;

	private int m_GridPos;
	public int GridPos
	{
		get { return m_GridPos; }
		set { m_GridPos = value; }
	}

	private int m_PlayerOwner;
	public int PlayerOwner
	{
		get { return m_PlayerOwner; }
		set { m_PlayerOwner = value; }
	}
	
	private bool m_EnablePlayerIcon;
	public bool EnablePlayerIcon
	{
		set { m_EnablePlayerIcon = value; }
	}
	
	private bool m_EnablePlayerScale;
	public bool EnablePlayerScale
	{
		set { m_EnablePlayerScale = value; }
	}
	
	private void Awake () 
	{
		m_PawnVisual = aTransform.GetChildByName("Visual").GetComponent<SpriteRenderer>();
	}

	private void Start () 
	{
		m_InitialScale = m_SpriteRenderer.transform.localScale;
		m_LargestMoveCheck = SimpleChessGame.Game.Columns < SimpleChessGame.Game.Rows ? SimpleChessGame.Game.Rows : SimpleChessGame.Game.Columns;
	}

	private void Update () 
	{
		if(!m_IsDead)
		{
			IconFeedback();
			ScaleFeedback();
		}
		else
		{
			if(!m_ReachedDeadPos)
			{
				DeadAnim();
			}
		}
	}

	private void IconFeedback()
	{		
		if(m_EnablePlayerIcon)
		{
			if(!m_PlayerIconNewAlphaReached)
			{
				m_PlayerIconFlickerTimer += Time.deltaTime;
				
				if(m_PlayerIconFlickerTimer >= m_PlayerIconFlickerTime)
				{
					m_PlayerIconNewAlphaReached = true;
				}
			}
			else
			{
				m_PlayerIconFlickerTimer -= Time.deltaTime;
				
				if(m_PlayerIconFlickerTimer <= 0)
				{
					m_PlayerIconNewAlphaReached = false;
				}
			}
			
			m_PlayerIconNewAlpha = m_PlayerIconRenderer.color;
			m_PlayerIconNewAlpha.a = (m_PlayerIconFlickerTimer)/m_PlayerIconFlickerTime - 0.25f;
			m_PlayerIconRenderer.color = m_PlayerIconNewAlpha;
		}
		else
		{
			if(m_PlayerIconRenderer.color.a != 0)
			{
				m_PlayerIconNewAlpha = m_PlayerIconRenderer.color;
				m_PlayerIconNewAlpha.a = 0;
				m_PlayerIconRenderer.color = m_PlayerIconNewAlpha;
			}
		}
	}

	private void ScaleFeedback()
	{
		if(m_EnablePlayerScale)
		{
			if(m_PlayerScaleReached)
			{
				m_SpriteRenderer.transform.localScale = Vector3.Lerp(m_SpriteRenderer.transform.localScale, m_InitialScale, m_PlayerScaleSpeed * Time.deltaTime);
				
				if(m_SpriteRenderer.transform.localScale.x <= m_InitialScale.x + 0.01f)
				{
					m_SpriteRenderer.transform.localScale = m_InitialScale;
					m_PlayerScaleReached = false;
				}
			}
			else
			{
				m_SpriteRenderer.transform.localScale = Vector3.Lerp(m_SpriteRenderer.transform.localScale, m_NewPlayerScale, m_PlayerScaleSpeed * Time.deltaTime);

				if(m_SpriteRenderer.transform.localScale.x >= m_NewPlayerScale.x - 0.01f)
				{
					m_SpriteRenderer.transform.localScale = m_NewPlayerScale;
					m_PlayerScaleReached = true;
				}
			}
		}
		else
		{
			if(aTransform.localScale != m_InitialScale)
			{
				m_PlayerScaleReached = false;
				m_SpriteRenderer.transform.localScale = m_InitialScale;
			}
		}
	}

	private void DeadAnim()
	{
		m_Animator.SetTrigger("IsDead");
		for(int i = 0; i < SimpleChessGame.Game.PlayersDeadPawn[m_PlayerOwner].Count; i++)
		{
			if(SimpleChessGame.Game.PlayersDeadPawn[m_PlayerOwner][i] == this)
			{
				Vector3 newPos;
				if(i == 0)
				{
					newPos = SimpleChessGame.Game.IconScore[m_PlayerOwner].transform.position;
					newPos.x -= 1.25f;
					newPos.y -= 0.85f;
				}
				else
				{
					newPos = SimpleChessGame.Game.PlayersDeadPawn[m_PlayerOwner][i - 1].aTransform.position;
					newPos.x += SimpleChessGame.Game.PlayersDeadPawn[m_PlayerOwner][i - 1].aTransform.localScale.x/2f + 0.1f;
				}

				aTransform.position = Vector3.Lerp(aTransform.position, newPos, m_DeadPosSpeed * Time.deltaTime);
				if(Vector3.Distance(aTransform.position, newPos) <= 0.001f)
				{
					m_ReachedDeadPos = true;
				}
			}
		}
	}

	public void SetPawnData(PawnValue pawnValue, int i_GridPos)
	{
		m_PawnValue = pawnValue;

		m_GridPos = i_GridPos;

		switch(pawnValue)
		{
		case PawnValue.Pawn:
			m_PawnMovement.Add(new PawnMovement(0, 1));
			m_PawnVisual.sprite = GetMatchingRenderer(pawnValue);
			break;

		case PawnValue.Bishop:
			//m_PawnMovement.Add(new PawnMovement(1, 1));
			m_PawnVisual.sprite = GetMatchingRenderer(pawnValue);
			break;

		case PawnValue.Knight:
			m_PawnMovement.Add(new PawnMovement(1, 3));
			m_PawnVisual.sprite = GetMatchingRenderer(pawnValue);
			break;

		case PawnValue.Rook:
			m_PawnMovement.Add(new PawnMovement(1, 1));
			m_PawnVisual.sprite = GetMatchingRenderer(pawnValue);
			break;

		case PawnValue.Queen:
			m_PawnMovement.Add(new PawnMovement(1, 1));
			m_PawnVisual.sprite = GetMatchingRenderer(pawnValue);
			break;
			
		case PawnValue.King:
			m_PawnMovement.Add(new PawnMovement(1, 1));
			m_PawnVisual.sprite = GetMatchingRenderer(pawnValue);
			break;
			
		}
	}

	private Sprite GetMatchingRenderer(PawnValue pawnValue)
	{
		for(int i = 0; i < m_PawnVisualList.Count; i++)
		{
			if(m_PawnVisualList[i].m_PawnValue == pawnValue)
			{
				return m_PawnVisualList[i].m_MatchingPawnRenderer;
			}
		}
		return null;
	}

	public List<int> GetPawnMovement(int gridPos)
	{
		List<int> move = new List<int>();
		
		switch(m_PawnValue)
		{
		case PawnValue.Pawn:
			break;
			
		case PawnValue.Bishop:
			move = GetPawnDataMovement(gridPos, PawnValue.Bishop);
			break;
			
		case PawnValue.Knight:
			move = GetPawnDataMovement(gridPos, PawnValue.Knight);
			break;
			
		case PawnValue.Rook:
			move = GetPawnDataMovement(gridPos, PawnValue.Rook);
			break;
			
		case PawnValue.Queen:
			move = GetPawnDataMovement(gridPos, PawnValue.Rook);

			List<int> tempMove = GetPawnDataMovement(gridPos, PawnValue.Bishop);
			for(int i = 0; i < tempMove.Count; i++)
			{
				move.Add(tempMove[i]);
			}
			break;
			
		case PawnValue.King:
			move = GetPawnDataMovement(gridPos, PawnValue.King);
			break;
		}

		return move;
	}

	private List<int> GetPawnDataMovement(int gridPos, PawnData.PawnValue i_PawnValue)
	{
		List<int> move = new List<int>();
		List<SimpleChessEmptySquare> squareList = SimpleChessGame.Game.SquareList;
		int totalSquare = SimpleChessGame.Game.TotalSquareNumber;
		int rows = SimpleChessGame.Game.Rows;
		int previous = gridPos;
		int squareToCheck;

		switch(i_PawnValue)
		{
		case PawnValue.Bishop:
			//NW
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos - ((rows - 1) * i);
				
				if(	squareToCheck >= 0 					&& 
				   squareToCheck < totalSquare 		&& 
				   previous % rows != rows - 1)
				{
					if(squareList[squareToCheck] == null || (previous >= 0 && previous < totalSquare && squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			
			previous = gridPos;
			//NE
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos + ((rows + 1) * i);
				
				if(	squareToCheck >= 0 					&& 
				   squareToCheck < totalSquare 		&& 
				   previous % rows != rows - 1)
				{
					if(squareList[squareToCheck] == null || (previous >= 0 && previous < totalSquare && squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			
			previous = gridPos;
			//SW
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos - ((rows + 1) * i);
				
				if(	squareToCheck >= 0 					&&
				   squareToCheck < totalSquare 			&& 
				   previous % rows != 0)
				{
					if(squareList[squareToCheck] == null || (previous >= 0 && previous < totalSquare && squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			
			previous = gridPos;
			//SE
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos + ((rows - 1) * i);
				
				if(	squareToCheck >= 0 					&& 
				   	squareToCheck < totalSquare 		&&
				   	previous % rows != 0)
				{
					if(squareList[squareToCheck] == null || (previous >= 0 && previous < totalSquare && squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			break;

		case PawnValue.Knight:
			// UUL
			squareToCheck = gridPos + (2 - rows);
			
			if(	squareToCheck >= 0 					&&
			   squareToCheck < totalSquare			&&
			   gridPos >= rows						&& 
			   gridPos % rows != rows - 1			&&
			   gridPos % rows != rows - 2			&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			
			// UUR
			squareToCheck = gridPos + (2 + rows);
			
			if(	squareToCheck >= 0 					&&
			   squareToCheck < totalSquare			&&
			   gridPos < totalSquare - rows		&&
			   gridPos % rows != rows - 1			&&
			   gridPos % rows != rows - 2			&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			
			// DDL
			squareToCheck = gridPos + (-2 - rows);
			
			if(	squareToCheck >= 0 			&&
			   squareToCheck < totalSquare	&&
			   gridPos >= rows				&& 
			   gridPos % rows != 0			&&
			   gridPos % rows != 1			&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			
			// DDR
			squareToCheck = gridPos + (-2 + rows);
			
			if(	squareToCheck >= 0 				&&
			   squareToCheck < totalSquare		&&
			   gridPos < totalSquare - rows	&&
			   gridPos % rows != 0				&&
			   gridPos % rows != 1				&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			
			// LLU
			squareToCheck = gridPos + (1 - (2 * rows));
			
			if(	squareToCheck >= 0 			&&
			   squareToCheck < totalSquare	&&
			   gridPos % rows != rows - 1	&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			
			// RRU
			squareToCheck = gridPos + (1 + (2 * rows));
			
			if(	squareToCheck >= 0 					&&
			   squareToCheck < totalSquare 		&&
			   gridPos < totalSquare - 2 * rows	&&
			   gridPos % rows != rows - 1			&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			
			// LLD
			squareToCheck = gridPos + (-1 - (2 * rows));
			
			if(	squareToCheck >= 0 					&&
			   squareToCheck < totalSquare			&&
			   gridPos >= 2 * rows					&&
			   gridPos % rows != 0					&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			
			// RRD
			squareToCheck = gridPos + (-1 + (2 * rows));
			
			if(	squareToCheck >= 0 				&&
			   squareToCheck < totalSquare		&&
			   gridPos < totalSquare - 2 * rows	&&
			   gridPos % rows != 0				&&
			   squareList[squareToCheck] != null)
			{
				move.Add(squareToCheck);
			}
			break;

		case PawnValue.Rook:
			previous = gridPos;
			// N
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos + i;
				
				if(	squareToCheck >= 0 				&& 
				   squareToCheck < totalSquare 		&& 
				   previous % rows != rows - 1)
				{
					if(squareList[squareToCheck] == null || (previous != gridPos && previous >= 0 && previous < totalSquare && squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			
			previous = gridPos;
			// E
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos + (rows * i);
				
				if(	squareToCheck >= 0 				&& 
				   squareToCheck < totalSquare 		&& 
				   previous < totalSquare - rows)
				{
					if(squareList[squareToCheck] == null || (previous != gridPos && previous >= 0 && previous < totalSquare && squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			
			previous = gridPos;
			// S
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos - i;
				
				if(	squareToCheck >= 0 			&& 
				   squareToCheck < totalSquare	&&
				   previous % rows != 0)
				{
					if(squareList[squareToCheck] == null || (previous != gridPos && previous >= 0 && previous < totalSquare && squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			
			previous = gridPos;
			// W
			for(int i = 1; i < m_LargestMoveCheck; i++)
			{
				squareToCheck = gridPos - (rows * i);
				
				if(	squareToCheck >= 0 			&& 
				   	squareToCheck < totalSquare && 
				   	previous >= rows)
				{
					if(squareList[squareToCheck] == null || (previous != gridPos && previous >= 0 && previous < totalSquare	&& squareList[previous].CurrentPawn != null))
					{
						if(squareList[previous].CurrentPawn != this)
						{
							break;
						}
					}
					
					move.Add(squareToCheck);
					previous = squareToCheck;
				}
			}
			break;
			
		case PawnValue.King:
			// N			
			squareToCheck = gridPos + 1;
			
			if(	squareToCheck >= 0 			&& 
			   	squareToCheck < totalSquare	&&
			   	gridPos % rows != rows - 1)
			{
				if(squareList[squareToCheck] == null)
				{
					break;
				}
				
				move.Add(squareToCheck);
			}
			
			// E		
			squareToCheck = gridPos + rows;
			
			if(	squareToCheck >= 0 				&& 
			   squareToCheck < totalSquare 		&& 
			   gridPos < totalSquare - rows)
			{
				if(squareList[squareToCheck] == null)
				{
					break;
				}
				
				move.Add(squareToCheck);
			}

			// S
			squareToCheck = gridPos - 1;
			
			if(	squareToCheck >= 0 			&& 
			   	squareToCheck < totalSquare	&&
			   	gridPos % rows != 0)
			{
				if(squareList[squareToCheck] == null)
				{
					break;
				}
				
				move.Add(squareToCheck);
			}

			// W
			squareToCheck = gridPos - rows;
			
			if(	squareToCheck >= 0 			&& 
			   	squareToCheck < totalSquare && 
			   	gridPos >= rows)
			{
				if(squareList[squareToCheck] == null)
				{
					break;
				}
				
				move.Add(squareToCheck);
			}

			break;
		}

		return move;
	}
}
